package main

import (
	"fmt"
	"sync"
)

func main() {
	fmt.Println(int(rune(0x03)))
}

type Pool[T any] struct {
	pool *sync.Pool
}

func (p *Pool[T]) Get() T {
	return p.pool.Get().(T)
}

func (p *Pool[T]) Put(x T) {
	p.pool.Put(x)
}

func NewPool[T any](fn func() T) *Pool[T] {
	p := &Pool[T]{
		pool: &sync.Pool{
			New: func() any {
				return fn()
			},
		},
	}
	return p
}

func NewPoolCh[T any](fn func() T, chLen int) *PoolCh[T] {
	return &PoolCh[T]{
		ch:   make(chan T, chLen),
		pool: NewPool(fn),
	}
}

type PoolCh[T any] struct {
	ch   chan T
	pool *Pool[T]
}

func (p *PoolCh[T]) Get() T {
	select {
	case x := <-p.ch:
		return x
	default:
		return p.pool.Get()
	}
}

func (p *PoolCh[T]) Put(x T) {
	select {
	case p.ch <- x:
	default:
		p.pool.Put(x)
	}
}
